package com.zhq.spring;

import com.sun.xml.internal.ws.util.StringUtils;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext  implements BeanFactory{
      private Class<?> configClass;

    /** 用于存放BeanDefinition **/
    private  ConcurrentHashMap<String,BeanDefintion> beanDefintionMap=new ConcurrentHashMap();

    /**单例bean的容器集合**/
    private final Map<String,Object> singletonObjects=new ConcurrentHashMap<>(256);

    public ApplicationContext(Class configClass){
        this.configClass=configClass;
        /* 表示是标注了@Component注解的，去扫描对应的bean组件**/
        if (configClass.isAnnotationPresent(ComponentScan.class)) {
            System.out.println("====已标注===");
            /** 获取该元素指定类型的注释。Class<A> annotationClass即为要获取什么样的注解,获取不到就返回空**/
            ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);

            if (annotation!=null) {
                /** 我们要去是扫描的路径(day1.src) **/
                String path = annotation.path();

                path=path.replace(".","/");

                ClassLoader classLoader = ApplicationContext.class.getClassLoader();
                URL resource = classLoader.getResource(path);
                if (resource==null){
                    throw new RuntimeException("请输入正确的路径！");
                }
                /** File既可以表示一个文件夹，也可以是一个文件 **/
                File file = new File(resource.getFile());

                if (!file.isDirectory()){
                    throw new RuntimeException("此路径不是一个文件夹！");
                }else {
                    File[] files = file.listFiles();
                    /** 找出.class文件 **/
                    for (File f:files){
                        String absolutePath = f.getAbsolutePath();
                        if (absolutePath.endsWith(".class")){
                            /** 判断是否标注了@Component注解，因为isAnnotionPresent()需要通过反射去得到 **/
                            /** 此处有只能通过 Class.forName(类的全限定类名)去得到一个class对象 **/
                            String com = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                            com=com.replace("\\",".");
                            try {
                                Class<?> aClass = Class.forName(com);
                                String simpleName = aClass.getSimpleName();
                                /**此时说明他是一个bean对象**/
                                boolean annotationPresent = aClass.isAnnotationPresent(Component.class);
                                /** 但是此时也不应该直接去创建这个对象 **/
                                if (annotationPresent){
                                    BeanDefintion beanDefintion=new BeanDefintion();
                                    beanDefintion.setBeanName(f.getName());
                                    boolean present = aClass.isAnnotationPresent(Scope.class);
                                    if (present){
                                        Scope scope = aClass.getAnnotation(Scope.class);
                                        if (!scope.isSingleton()) {
                                            beanDefintion.setSingleton(false);
                                        }
                                    }else {
                                        /** 没有@Scope注解那么就默认为是单例对象，创建BeanDefintion **/
                                        beanDefintion.setSingleton(true);
                                    }
                                    beanDefintionMap.put(f.getName(),beanDefintion);
                                }
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }

                        }
                    }
                }
            }
        }
    }

    /**
     * getBean()从容器中获取一个bean对象
     *
     * @param beanName
     **/
    @Override
    public Object getBean(String beanName) {
        if (!beanDefintionMap.containsKey(beanName)){
            throw new NullPointerException();
        }else{
            BeanDefintion beanDefintion = beanDefintionMap.get(beanName);
            /** 是单例对象之间从单例池中获取 ***/
            if (beanDefintion.getSingleton()){
                Object object = singletonObjects.get(beanName);
                if (object==null){
                    object= createBean(beanDefintion,beanName);
                    singletonObjects.put(beanName,object);
                }
                return object;
            }else {
                /** 不是单例的直接创建一个对象 ***/
                Object bean = createBean(beanDefintion,beanName);
                return bean;
            }
        }
    }

    private Object createBean(BeanDefintion beanDefintion,String beanName) {
        if (beanDefintion.getSingleton()){
            /*** 是单例 ***/
        }
        this.createBeanInstance();
        return null;
    }

    /** 根据不同的参数类型去创建bean对象 ***/
    private void createBeanInstance() {

    }

    @Override
    public <T> T getBean(Class<T> clazz) {
        return null;
    }
}
